<?php
class Security {
     /**
     * 生成密码哈希 (自动选择最佳算法)
     */
    public static function hashPassword(string $password): string {
        if (empty($password)) {
            throw new Exception("密码不能为空");
        }
        
        // 添加pepper增强安全性
        $peppered = hash_hmac('sha256', $password, defined('PEPPER') ? PEPPER : 'default_pepper_please_change_me');
        
        // 尝试使用Argon2ID (不带线程参数)
        if (defined('PASSWORD_ARGON2ID') && PASSWORD_ARGON2ID) {
            $options = [
                'memory_cost' => 1024 * 16,  // 减少内存使用量
                'time_cost' => 3             // 减少迭代次数
            ];
            $hash = @password_hash($peppered, PASSWORD_ARGON2ID, $options);
            if ($hash !== false && $hash !== null) {
                return $hash;
            }
        }
        
        // 回退到BCRYPT
        $hash = password_hash($peppered, PASSWORD_BCRYPT, ['cost' => 10]);
        if ($hash === false || $hash === null) {
            throw new Exception("密码哈希生成失败");
        }
        
        return $hash;
    }

    /**
     * 验证密码
     */
    public static function verifyPassword(string $password, string $hash): bool {
        $peppered = hash_hmac('sha256', $password, defined('PEPPER') ? PEPPER : 'default_pepper_please_change_me');
        return password_verify($peppered, $hash);
    }

    /**
     * 生成加密Token (CSRF安全)
     */
    public static function generateToken(int $userId): string {
        $random = bin2hex(random_bytes(32));
        $data = $userId . '|' . time() . '|' . $random;
        return bin2hex(openssl_encrypt(
            $data,
            'aes-256-ctr',
            PEPPER,
            OPENSSL_RAW_DATA,
            substr(hash('sha256', PEPPER), 0, 16)
        ));
    }

    /**
     * 解析验证Token
     */
    public static function parseToken(string $token): ?array {
        $decrypted = openssl_decrypt(
            hex2bin($token),
            'aes-256-ctr',
            PEPPER,
            OPENSSL_RAW_DATA,
            substr(hash('sha256', PEPPER), 0, 16)
        );
        
        if (!$decrypted) return null;
        
        $parts = explode('|', $decrypted);
        if (count($parts) !== 3) return null;

        return [
            'user_id' => (int)$parts[0],
            'timestamp' => (int)$parts[1],
            'random' => $parts[2]
        ];
    }
}